package com.caltco.cargo.ops.modules.sys.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caltco.cargo.ops.common.exception.RRException;
import com.caltco.cargo.ops.modules.sys.dao.TaskFileDao;
import com.caltco.cargo.ops.modules.sys.entity.Task;
import com.caltco.cargo.ops.modules.sys.entity.TaskFile;
import com.caltco.cargo.ops.modules.sys.service.TaskFileService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

@Service
@AllArgsConstructor
public class TaskFileServiceImp extends ServiceImpl<TaskFileDao, TaskFile> implements TaskFileService {
    private final TaskFileDao taskFileDao;
    private final String imgPosition = "D://image/";
    @Override
    public String storeFile(MultipartFile file, String path) throws IllegalStateException, IOException {
        // 获取原始文件名
        String fileName = file.getOriginalFilename();
        // // 获取文件后缀
        // String suffixName = fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".")) : null;
        // //文件的保存重新按照时间戳命名
        // String newFileName = System.currentTimeMillis() + suffixName;
        // 最终保存的文件
        File filePath = new File(path + File.separator + fileName);
        // 判断文件夹是否存在
        if (!filePath.getParentFile().exists()) {
            filePath.getParentFile().mkdirs();
        }
        // 保存文件
        file.transferTo(filePath);
        // 如果成功，会返回文件的绝对路径，方便下载
//        logger.info("文件已保存至" +filePath.toString());
        return filePath.toString();
    }


    @Override
    public Map<String, Object> batchUploadFile(MultipartFile[] files, Long taskId) {
        Map<String, Object> mapData = new HashMap<>();
        //step 1: 判断校验文件流是否有文件
        if (files == null || files.length == 0) {
            mapData.put("success", false);//false:成功，false:失败
            mapData.put("msg", "系统未检测到文件流");
            return mapData;
        }
        //step 2: 创建List集合用于存储文件对象
        List<TaskFile> taskFileList = new ArrayList<>();
        //step 3: 创建List集合用于存储文件ID，返给前端
        List<String> taskFileIdList = new ArrayList<>();

        for (MultipartFile file : files) {

            //step 4: 封装实例对象
            TaskFile taskFile = new TaskFile();
            String fileId = String.valueOf(UUID.randomUUID());
            taskFile.setId(fileId);//文件id
            taskFile.setTaskId(taskId);//操作用户id

            // 获取原始名字
            String fileNameUp = file.getOriginalFilename();
            taskFile.setFileNameUp(fileNameUp);//上传文件名称

            taskFile.setFileName(fileId);//存储文件的名称

            // 获取后缀名
            String suffixType = fileNameUp.substring(fileNameUp.lastIndexOf(".") + 1);
            taskFile.setFileType(suffixType);//文件类型

            //获得文件大小
            Float size = Float.parseFloat(String.valueOf(file.getSize())) / 1024;
            BigDecimal b = new BigDecimal(size);
            size = b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
            taskFile.setFileSize(Double.valueOf(size));//文件大小（字节单位）

            // 文件保存路径 你还可以在拼接一层路径，例如 20210521 每天上传的都会生成一个新的文件加里
            String filePath = imgPosition;
            taskFile.setFilePath(filePath);//文件上传路径

            // 文件重命名，防止重复
            String filePathName = filePath + fileId + "." + taskFile.getFileType();
            //本机ip 静态方法获取InetAddress对象。
            InetAddress ia = null;
            try {
                ia = ia.getLocalHost();// 获取本地主机
                taskFile.setServerIp(ia.getHostAddress());
            } catch (UnknownHostException e) {
                log.error("文件传输服务器失败:", e);
            }
            //step 5: 创建文件对象
            File dest = new File(filePathName);
            //step 6: 判断路径是否存在，如果不存在则创建
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }

            //step 7: 文件存在，返回
            if (dest.exists()) {
                mapData.put("success", false);//false:成功，false:失败
                mapData.put("msg", "文件已存在,请重新上传" + fileNameUp);
                return mapData;
            }
            try {
                //step 8: 保存到服务器中
                file.transferTo(dest);
                //step 9: 将生产的文件ID 和文件对象分别存入对应的集合
                taskFileIdList.add(fileId);
                taskFileList.add(taskFile);
            } catch (Exception e) {
                log.error("文件传输服务器失败:", e);
            }
        }
        //判断校验存储文件对象集合是否为空、集合长度是否大于0
        if (taskFileList != null && taskFileList.size() > 0) {
            //step 10: 批量添加文件对象
            Boolean i = this.saveBatch(taskFileList);
            //step 11: 判断是否添加成功  存储文件对象的集合长度是否等于数据库执行的条数
            if (i) {
                mapData.put("success", true);//false:成功，false:失败
                mapData.put("msg", "文件上传成功");
                mapData.put("data", taskFileIdList);
                return mapData;
            }
        }
        mapData.put("success", false);//false:成功，false:失败
        mapData.put("msg", "文件上传失败");
        return mapData;
    }

    @Override
    public List<TaskFile> getAllFiles(Long taskId) {
        MPJLambdaWrapper<TaskFile> mpjLambdaWrapper = new MPJLambdaWrapper<TaskFile>()
                .leftJoin(Task.class, Task::getId, TaskFile::getTaskId)
                .eq(Task::getId, taskId);
        return taskFileDao.selectList(mpjLambdaWrapper);
    }

    @Override
    public Boolean deleteFiles(List<String> fileIds) {
        // 从请求中获取文件名列表
//        List<String> fileIds = (List<String>) request.get("id");
        if (fileIds == null || fileIds.isEmpty()) {
            Map<String, Object> response = new HashMap<>();
            response.put("success", false);
            response.put("msg", "文件列表为空");
            throw new RRException("删除失败");
        }

        // 记录删除结果：成功删除的文件、文件删除失败的、以及未找到对应记录的文件

        List<TaskFile> taskFiles = this.listByIds(fileIds);
        for (TaskFile taskFile : taskFiles) {

            if (taskFile != null) {
                boolean fileDeleted = false;
                String path = taskFile.getFilePath() + taskFile.getId() + "." + taskFile.getFileType();
                File file = new File(path);
                try {
                    // 如果文件存在则尝试删除，不存在则认为已删除
                    if (file.exists()) {
                        fileDeleted = file.delete();
                    } else {
                        fileDeleted = true;
                    }
                } catch (Exception e) {
                    fileDeleted = false;
                }
                try {
                    // 无论文件是否成功删除，都删除数据库记录
                    this.removeBatchByIds(fileIds);
                } catch (Exception e) {
                    // 如果数据库删除失败，则视为整体删除失败
                    fileDeleted = false;
                }
            }

        }

        return true;
    }

//    @Override
//    public Boolean batchDownloadFile(List<String> files, HttpServletRequest request, HttpServletResponse response) {
//        //step 1: 判断校验参数信息是否为空
//        if (files == null || files.size() <= 0) {
//            return true;
//        }
//        TaskFile taskFile = taskFileService.getFileById(fileId);
//        if (taskFile == null) {
//            return ResponseEntity.notFound().build();
//        }
//        Path path = Paths.get(taskFile.getFilePath(), taskFile.getFileName());
//        Resource resource;
//        try {
//            resource = new UrlResource(path.toUri());
//            if (!resource.exists()) {
//                return ResponseEntity.notFound().build();
//            }
//        } catch (MalformedURLException e) {
//            return ResponseEntity.badRequest().build();
//        }
//        return ResponseEntity.ok()
//                .contentType(MediaType.parseMediaType("application/octet-stream"))
//                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + taskFile.getFileNameUp() + "\"")
//                .body(resource);
//        return true;
//    }

}

